﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

using Microsoft.Research.Kinect.Nui;
using KinectUserManager;
using KinectXNATools;

namespace KinnectInput
{
    public enum SkeletonStatus
    {
        Waiting,
        Success,
        UserLost
    }
    public enum UserState
    {
        NoUser,
        UserClipped,
        TwoUsers,
        Active
    }
    public class SkeletalManager
    {
        Runtime KinectSkelletonRuntime;
        public UserAsserter MainUser { get; private set; }
        //el esqueleto

        public UserState ActiveUserState { get; set; }
        public SkeletonStatus status { get; set; }
        bool isKinectDistance= true;
        public bool IsKinectDistance { get { return isKinectDistance; } }
        public string ClippedMessage = "";
        GraphicsDevice gDev;
        Dictionary<JointID, Vector2> _jointPosition;
        public Dictionary<JointID, Vector2> JointPosition 
        { 
            get 
            {
                
                if (MainUser != null)
                {
                    JointID[] ids = MainUser.PlayerOneJoints.Keys.ToArray();
                    bool wasHead = false;
                    for (int i = 0; i < MainUser.PlayerOneJoints.Count; i++)
                    {
                        JointID JID = ids[i];
                        _jointPosition[JID]= this.getDisplayPosition(TrakedSkeletonManager.TrakedSkelletons[0].Joints[JID]);
                    }
                    foreach(JointID j in _jointPosition.Keys){
                        if (j == JointID.Head)
                        {
                            wasHead = true;
                        }
                    }
                    if (MainUser.firstUserID!=-1 && TrakedSkeletonManager.TrakedSkelletons[0].Joints[JointID.Head].Position.Z < 1.5f)
                    {
                        this.isKinectDistance = false;
                    }
                    else if (wasHead)
                    {
                        this.isKinectDistance = true;
                    }
                    
                }
                
                return _jointPosition; 
            } 
        }
        Texture2D tex;

        public Texture2D depth { get; private set; }
        public ImageResolution depthResolution;

        //constructor
        public SkeletalManager(GraphicsDevice gDev, ImageResolution depthResolution)
        {
            this.gDev = gDev;
            tex = new Texture2D(gDev, 1, 1);
            tex.SetData(new Color[] { Color.White });
            this.ActiveUserState = UserState.NoUser;
            this.status = SkeletonStatus.Waiting;
            this.depthResolution = depthResolution;
            //instancio kinect
            KinectSkelletonRuntime = Runtime.Kinects[0];
            //int JointIDLeanght = (int)JointID.Count;
            _jointPosition=new Dictionary<JointID,Vector2>();
            Array idss = Enum.GetValues(typeof(JointID));
            for (int i = 0; i < idss.Length;i++ )
            {
                _jointPosition.Add((JointID)(idss.GetValue(i)), Vector2.Zero);
            }

        }
        public void InicializeCamera()
        {
            //inicializo
            KinectSkelletonRuntime.Initialize(RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseDepth);
            KinectSkelletonRuntime.DepthStream.Open(ImageStreamType.Depth, 4, ImageResolution.Resolution640x480, ImageType.Depth);
            //Vamos a darle smoothing a ver si reacciona mejor
            KinectSkelletonRuntime.SkeletonEngine.SmoothParameters = new TransformSmoothParameters()
            {
                Prediction = 0,
                Correction = 0,
                MaxDeviationRadius = 0.04f,
                JitterRadius = 0.5f,
                Smoothing = 0.75f
            };
            this.MainUser = new UserAsserter(this.KinectSkelletonRuntime);
            this.status = SkeletonStatus.Success;
            MainUser.NewUserFound += new NewUserEventHandler(MainUser_NewUserFound);
            MainUser.UserLost += new UserLostEventHandler(MainUser_UserLost);
            //Eventos implementados en kinect input interpreter
        }

        void MainUser_UserLost(object sender, UserLostEventArgs e)
        {
            for (int i = 0; i < _jointPosition.Count; i++)
            {
                _jointPosition[_jointPosition.Keys.ToArray()[i]] = Vector2.Zero;
            }
        }

        void MainUser_NewUserFound(object sender, NewUserEventArgs e)
        {
            isKinectDistance = true;
        }

        private Vector2 getDisplayPosition(Joint joint)
        {

            float depthX, depthY;
            KinectSkelletonRuntime.SkeletonEngine.SkeletonToDepthImage(joint.Position, out depthX, out depthY);
            depthX = Math.Max(0, Math.Min(depthX * 320, gDev.Viewport.Width));//pasar  de  320 a screen space
            depthY = Math.Max(0, Math.Min(depthY * 240, gDev.Viewport.Height));//de 320 ascreen space
            int colorX, colorY;
            ImageViewArea iv = new ImageViewArea();

            KinectSkelletonRuntime.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(ImageResolution.Resolution640x480, iv, (int)depthX, (int)depthY, (short)0, out colorX, out colorY);
            
            //falta adaptar para cualquier resolucion
            return new Vector2((int)(this.gDev.Viewport.Width * colorX / 640.0), (int)(this.gDev.Viewport.Height * colorY / 480));

        }
        
        public void Draw(SpriteBatch sb, SpriteFont sf)
        {
            Rectangle size=new Rectangle(0,0,160,120);
            Texture2D tex = Texture2DHelper.SkelletonImage(TrakedSkeletonManager.TrakedSkelletons, this.KinectSkelletonRuntime, size, this.gDev, Color.Red, Color.WhiteSmoke, 3, Color.GreenYellow, Color.WhiteSmoke, 3, Color.Black);
            Rectangle toDrawRect = new Rectangle(gDev.Viewport.Bounds.Width - size.Width, gDev.Viewport.Bounds.Height - size.Height, size.Width, size.Height);
            sb.Draw(tex, toDrawRect, Color.White);
            if (MainUser.firstUserID != -1)
            {
                //sb.DrawString(sf, "" + this.MainUser.PlayerOneJoints[JointID.Head], Vector2.Zero, Color.White);
            }
        }

    }

    
}

